package zzg.study.reactor;

import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.*;

/**
 * @Classname Server
 * @Description TODO
 * @Date 2025/1/27 16:19
 * @Author zhuzhenguo
 */
public class Server {
    private int port;

    private Acceptor acceptor;

    private Set<PollerIO> ioThreads;

    private ExecutorService buExecutor;

    public volatile boolean stopped = true;

    public int getPort() {
        return port;
    }

    public void setPort(int port) {
        this.port = port;
    }

    public Acceptor getAcceptor() {
        return acceptor;
    }

    public void setAcceptor(Acceptor acceptor) {
        this.acceptor = acceptor;
    }

    public Set<PollerIO> getIoThreads() {
        return ioThreads;
    }

    public void setIoThreads(Set<PollerIO> ioThreads) {
        this.ioThreads = ioThreads;
    }

    public ExecutorService getBuExecutor() {
        return buExecutor;
    }

    public void setBuExecutor(ExecutorService buExecutor) {
        this.buExecutor = buExecutor;
    }

    public boolean isStopped() {
        return stopped;
    }

    public void setStopped(boolean stopped) {
        this.stopped = stopped;
    }

    public void init() {
        this.port = 9999;
        int ioThreadNum = 4;
        this.ioThreads = new HashSet<>(ioThreadNum);
        // 准备io线程
        for (int i = 0; i < ioThreadNum; i++) {
            PollerIO ioThread = new PollerIO("PollerIO-" + i, this);
            this.ioThreads.add(ioThread);
        }
        // 启动acceptor
        try {
            this.acceptor = new Acceptor("acceptor", this, this.ioThreads);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public void start() {
        // 开始bu线程
        this.buExecutor = new ThreadPoolExecutor(
                200,
                500,
                60,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(1000)
        );
        // 开始io线程
        for (PollerIO ioThread : this.ioThreads) {
            ioThread.start();
        }
        this.acceptor.start();
    }

    public void shutdown() {
        this.stopped = true;
        this.buExecutor.shutdown();
    }

    public static void main(String[] args) {
        CountDownLatch latch = new CountDownLatch(1);
        Server server = new Server();
        server.init();
        server.start();
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            server.shutdown();
            latch.countDown();
        }));
        try {
            latch.await();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }

    public void addBuTask(BuTask task) {
        this.buExecutor.execute(task);
    }
}
